package org.aspectsense.middleware.adaptation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;

import org.aspectsense.middleware.ComponentContainer;
import org.aspectsense.middleware.Repository;
import org.aspectsense.middleware.gui.MainFrame;


public final class AdaptationGraph {

	private static LinkedList <BigraphComponentNode> componentsSet = new LinkedList<BigraphComponentNode>();
	private static LinkedHashMap <String,BigraphServiceNode> servicesSet = new LinkedHashMap<String, BigraphServiceNode>();
	public static LinkedList <BigraphComponentNode> maxComponents = new LinkedList <BigraphComponentNode> ();

	public static LinkedList <HashMap<BigraphServiceNode,BigraphComponentNode>> maxPaths; 
	//---------Thread-safe Singleton For Ensuring single instantiation of Repository
	public final static AdaptationGraph INSTANCE = new AdaptationGraph();
	private AdaptationGraph()
	{
		// Exists only to defeat instantiation.
	}
	//---------------------------------------
	
	public static void setGuiTree ()
	{
		LinkedList<BigraphAdaptationTree> provisionTrees =  AdaptationManager.provisionTrees; 
		Iterator <BigraphAdaptationTree> treeItr = provisionTrees.iterator();
		BigraphAdaptationTree tree;
		LinkedList <BigraphComponentNode> chain;
		Iterator <BigraphComponentNode> nodesItr;
		BigraphComponentNode node;
		BigraphServiceNode snode;
		HashSet <String>comps = new HashSet <String> ();
		
		ComponentContainer cc;
		componentsSet.clear();
		servicesSet.clear();
		comps.clear();
		//System.out.println ("End-User Services found:"+provisionTrees.size());
		while (treeItr.hasNext())
		{
			
			tree = treeItr.next();
			if (!tree.isResolved())
				continue;
			//System.out.println ("Tree for "+tree.getRoot().getBundleName());
			chain = tree.getTree();
			nodesItr = chain.iterator();
			//Iterate through all BigraphComponentNodes
			//and find unique components contributing in service provision
			while (nodesItr.hasNext())
			{
				node = nodesItr.next();
				if (!comps.contains(node.getContainer().getProviderName()))
				{
					componentsSet.add(node);
					comps.add(node.getContainer().getProviderName());
					//System.out.println ("Adding component:"+node.getContainer().getBundleName());
					//For any service provided by components
					//check if a BigraphServiceNode exists, if not create it
					cc = node.getContainer();
					for (String s: cc.getProvidedServicesClassNames())
					{
						if (servicesSet.get(s)==null)
						{
							snode = new BigraphServiceNode(s);
							if (cc.getEndUserServices()!=null && cc.getEndUserServices().length>0)
							{
								snode.setEndUser(true);
								//System.out.println (snode.getServiceName()+" is an end-user service");
							}
							else
							{
								snode.setEndUser(false);
								//System.out.println (snode.getServiceName()+" is NOT an end-user service");
							}
							servicesSet.put(s, snode);
							node.addConnection (snode);
						}
						else
							node.addConnection(servicesSet.get(s));
					}
					for (String s: cc.getRequiredServicesClassNames())
					{
						snode = servicesSet.get(s);
						if (snode==null)
						{
							System.out.println ("ERROR Unknown service found!"+s);
						}
						else
						{
							snode =servicesSet.get(s);
							snode.addConnection(node);
							servicesSet.put(s, snode);
						}
					}
				}
			}
			
		}
		
		MainFrame.rePaintOverviewGraph();
	}
	public static LinkedList <BigraphComponentNode> getComponents ()
	{
		return componentsSet;
	}
	public static HashMap <String,BigraphServiceNode> getServices ()
	{
		return servicesSet;
	}

	public static void setMaxGuiTree() 
	{
		LinkedList<LinkedList<BigraphComponentNode>> maxProvisionTrees =  AdaptationManager.maxProvisionTrees; 
		LinkedList<BigraphComponentNode> maxChain;
		maxComponents.clear();
	
		for (LinkedList<BigraphComponentNode> tree:maxProvisionTrees)
		{
			maxChain = tree;
			for (BigraphComponentNode node:maxChain)
			{
				if (node==null)
					System.out.println ("maxProvisionTrees contains null node");
				maxComponents.add(node);
			
			}
		}
	}
	
}